<?php

declare(strict_types=1);
/**
 * 请求日志
 * Author: Zane
 * Email: 873934580@qq.com
 * Date: 2022/3/26.
 */

namespace App\Service;

use App\Models\Log;
use Illuminate\Http\JsonResponse;
use Illuminate\Routing\Route;
use Illuminate\Support\Facades\Config;

class LogService
{
    public static function log($request, $response, $route): void
    {
        // 如果是控制台执行则不做任何记录
        if (false !== strpos(\PHP_SAPI, 'cli')) {
            return;
        }

        $log = new static();
        if (!$log->isRecord((string) $request->getMethod(), (int) $response->getStatusCode())) {
            return;
        }
        $data = [];
        $data['controller'] = '';
        $data['action'] = '';
        if ($route instanceof Route) {
            $data['controller'] = \get_class($route->getController());
            $data['action'] = $route->getActionMethod();
        }
        $data['ip'] = $request->getClientIp();
        $data['url'] = $request->getPathInfo();
        $data['title'] = $log->getTitle();
        $data['method'] = $request->getMethod();
        $data['request'] = $log->getRequestContent($request->all());
        $data['response'] = $log->getResponseContent($response);
        $data['response_code'] = $response->getStatusCode();
        $data['response_time'] = $log->getTime();
        // $data['sql_param'] = json_encode(LogSqlService::getSqlResults());

        Log::query()->create($data);
    }

    /**
     * 返回请求参数内容.
     *
     * @param $data
     *
     * @return string
     */
    private function getRequestContent($data): string
    {
        // 剔除敏感信息的记录
        $notAllow = ['password'];
        foreach ($notAllow as $value) {
            if (isset($data[$value])) {
                unset($data[$value]);
            }
        }

        return @json_encode($data);
    }

    /**
     * 返回响应参数.如果有结果级则不返回.
     *
     * @param $response
     *
     * @return string
     */
    private function getResponseContent($response): string
    {
        $res = '';
        if ($response instanceof JsonResponse) {
            $res = $response->getContent();

            try {
                $res = json_decode($res, true);
                if (isset($res['data']) && $res['data']) {
                    unset($res['data']);
                }
                $res = json_encode($res);
            } catch (\Exception $e) {
                $res = [
                    'code' => $e->getCode(),
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                ];
                $res = json_encode($res);
            }
        }
        if (200 !== $response->getStatusCode() && $response->exception) {
            $error = [
                'code' => $response->exception->getCode(),
                'file' => $response->exception->getFile(),
                'line' => $response->exception->getLine(),
                'message' => $response->exception->getMessage(),
            ];
            $res = json_encode($error);
        }

        return $res;
    }

    /**
     * 获取请求名称.
     *
     * @return string
     */
    private function getTitle(): string
    {
        return '';
    }

    private function getTime(): float
    {
        if (false === \defined('LARAVEL_START')) {
            return 0;
        }

        return round((microtime(true) - LARAVEL_START) * 1000, 2);
    }

    /**
     * 是否记录日志.
     *
     * @param string $method
     * @param int    $code
     *
     * @return bool
     */
    private function isRecord(string $method, int $code): bool
    {
        $methods = Config::get('logging.custom.method');
        if (200 !== $code) {
            return true;
        }
        if (\is_array($methods) && \in_array($method, $methods, true)) {
            return true;
        }

        return false;
    }
}
